using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace CoreLibrary.Template {

    public class SimpleTemplate : ITemplate{

        private readonly List<SimpleSegment> _segments = new List<SimpleSegment>();
        private static readonly Regex Pattern = new Regex(@"(\$\{([a-zA-Z0-9_]*)\})", RegexOptions.Compiled);

        public string Generate(TemplateParameters parameters) {
            return StringUtil.Join(string.Empty, _segments,
                seg => {
                    if (!seg.IsExpr) {
                         return Util.GetString(seg.Text);
                    }

                    Asserts.NotNull(parameters.Get(seg.Text), "No Parameter Found for [" + seg.Text+ "]");
                    return Util.GetString(parameters.Get(seg.Text));
                }
            );
        }

        private void AddText(string value) {
            _segments.Add(SimpleSegment.Create(value));
        }

        private void AddExpression(string value) {
            _segments.Add(SimpleSegment.Create(value, true));
        }

        public static SimpleTemplate Load(string input) {
            var template = new SimpleTemplate();
            var match    = Pattern.Match(input);
            if (!match.Success) {
                 template.AddText(input);
            }

            var start = 0;
            while(match.Success) {
                var outer = match.Groups[1];
                var inner = match.Groups[2];

                if (outer.Index == start) {
                    template.AddExpression(input.Substring(inner.Index, inner.Length));
                } else if (outer.Index > start) {
                    template.AddText(input.Substring(start, outer.Index - start));
                    template.AddExpression(input.Substring(inner.Index, inner.Length));
                }

                start = outer.Index + outer.Length;
                match = match.NextMatch();
            }

            return template;
        }

        private SimpleTemplate() {

        }

        internal class SimpleSegment {

            public bool IsExpr { get; set; }
            public string Text { get; set; }

            public static SimpleSegment Create(string value) {
                return Create(value, false);
            }

            public static SimpleSegment Create(string value, bool isExpression) {
                return new SimpleSegment {
                       Text   = value,
                       IsExpr = isExpression
                };
            }
        }

    }

}